
#include "lpc.h"

static PFLT_PORT g_ServerPort = NULL;
static PFLT_PORT g_ClientPort = NULL;
static PFLT_FILTER g_Filter = NULL;



BOOLEAN	get_user_judge(PVOID psendBuf, ULONG send_size, PSCANNER_REPLY pBret, PLARGE_INTEGER time_out)
{
	PVOID pBuf = NULL;
	ULONG replyLength = sizeof(SCANNER_REPLY);
	NTSTATUS status = 0;

	if (psendBuf == NULL || pBret == NULL || send_size == 0)
	{
		return FALSE;
	}

	pBuf = ExAllocatePoolWithTag(PagedPool, send_size, 'lpc');
	if (NULL == pBuf)
	{
		return FALSE;
	}
	RtlZeroMemory(pBuf, send_size);
	RtlCopyMemory(pBuf, psendBuf, send_size);

	status = FltSendMessage(g_Filter,
		&g_ClientPort,
		pBuf,
		send_size,
		pBuf,
		&replyLength,
		time_out);
	if (STATUS_SUCCESS == status)
	{
		
		RtlCopyMemory(pBret, pBuf, sizeof(SCANNER_REPLY));
		if (pBuf)
		{
			ExFreePool(pBuf);
		}
		return TRUE;
	}
	else
	{
		if (pBuf)
		{
			ExFreePool(pBuf);
		}
		return FALSE;
	}
}

NTSTATUS
PortConnect(
__in PFLT_PORT ClientPort,
__in_opt PVOID ServerPortCookie,
__in_bcount_opt(SizeOfContext) PVOID ConnectionContext,
__in ULONG SizeOfContext,
__deref_out_opt PVOID *ConnectionCookie
)
{
	PAGED_CODE();

	UNREFERENCED_PARAMETER(ServerPortCookie);
	UNREFERENCED_PARAMETER(ConnectionContext);
	UNREFERENCED_PARAMETER(SizeOfContext);
	UNREFERENCED_PARAMETER(ConnectionCookie);

	g_ClientPort = ClientPort;

	return STATUS_SUCCESS;
}


VOID
PortDisconnect(
__in_opt PVOID ConnectionCookie
)
{
	UNREFERENCED_PARAMETER(ConnectionCookie);
	PAGED_CODE();
	if (g_ClientPort)
	{
		FltCloseClientPort(g_Filter, &g_ClientPort);
		g_ClientPort = NULL;
	}
}









void uninit_lpc()
{
	if (g_ServerPort)
	{
		FltCloseCommunicationPort(g_ServerPort);
		g_ServerPort = NULL;
	}
}
NTSTATUS init_lpc_con(PFLT_FILTER filter)
{
	OBJECT_ATTRIBUTES		oa;
	UNICODE_STRING		uniString;
	PSECURITY_DESCRIPTOR	sd;
	NTSTATUS				status;

	g_Filter = filter;
	RtlInitUnicodeString(&uniString, L"\\gdlpcport");
	status = FltBuildDefaultSecurityDescriptor(&sd, FLT_PORT_ALL_ACCESS);
	if (NT_SUCCESS(status))
	{

		InitializeObjectAttributes(&oa, &uniString, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, NULL, sd);
		status = FltCreateCommunicationPort(filter,
			&g_ServerPort,
			&oa,
			NULL,
			PortConnect,
			PortDisconnect,
			NULL,
			1);
		FltFreeSecurityDescriptor(sd);
	}
	return status;
}


NTSTATUS init_lpc(PWCHAR port_name, PFLT_FILTER filter)
{
	OBJECT_ATTRIBUTES		oa;
	UNICODE_STRING			uniString;
	PSECURITY_DESCRIPTOR	sd;
	NTSTATUS				status;

	g_Filter = filter;
	RtlInitUnicodeString(&uniString, port_name);
	status = FltBuildDefaultSecurityDescriptor(&sd, FLT_PORT_ALL_ACCESS);
	if (NT_SUCCESS(status))
	{

		InitializeObjectAttributes(&oa, &uniString, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, NULL, sd);
		status = FltCreateCommunicationPort(filter,
			&g_ServerPort,
			&oa,
			NULL,
			PortConnect,
			PortDisconnect,
			NULL,
			1);
		FltFreeSecurityDescriptor(sd);
	}
	return status;
}